<template>
  <div>
    <ul class="file-list">
      <li v-for="(item, index) in uploadFile" :style="fileType == 1 ? '' : { width: '100%' }">
        <div v-if="fileType === 1" class="demo-upload-list" :class="{ 'clear-margin': clearMargin }">
          <img :style="isCut ? { 'object-fit': 'cover', 'width': '100%' } : { width: '100%' }" :src="item.url" alt="">
          <div class="demo-upload-list-cover">
            <Icon type="ios-eye-outline" style="margin-top: 36px" @click.native="handleView(item)" />
            <template v-if="needRemove">
              <Icon
                v-if="ifEdit"
                type="ios-trash-outline"
                style="margin-top: 36px"
                @click.native="handleRemove(index, item)"
              />
            </template>
            <template v-else>
              <Icon
                v-if="ifEdit"
                :type="computeIcon"
                size="20"
                style="margin-top: 36px"
                @click.native="handleTrackUpload(index, item)"
              />
            </template>
          </div>
        </div>
        <div
          v-if="fileType === 2"
          style="width: 100%; display: flex; align-items: center; justify-content: space-between"
        >
          <audio style="width: 90%" :src="item.url" controls="controls" />
          <Icon
            v-if="ifEdit"
            type="ios-trash"
            size="20"
            style="color: red; cursor: pointer"
            @click.native="handleRemove(index, item)"
          />
        </div>
        <div
          v-if="fileType === 3"
          style="display: flex; align-items: center; justify-content: space-between; position: relative"
        >
          <video
            style="width: 200px; height: 200%"
            :src="item.url"
            :poster="item.videoCover"
            controls="controls"
          />
          <Icon
            v-if="ifEdit"
            type="ios-trash"
            size="20"
            style="color: red; cursor: pointer"
            @click.native="handleRemove(index, item)"
          />
          <div
            style="
                            width: 100px;
                            height: 100px;
                            background: rgba(0, 0, 0, 0);
                            position: absolute;
                            left: 0px;
                            z-index: 1;
                        "
            @click="handleView(item)"
          />
        </div>
      </li>
      <li v-show="uploadFile.length < maxLength && ifEdit" class="file-list_upload">
        <Upload
          v-if="fileType != 2"
          ref="uploadLogRef"
          :headers="headers"
          :multiple="multiple"
          :show-upload-list="showUploadList"
          :format="format"
          :accept="accept"
          :max-size="maxSize"
          :data="data"
          :before-upload="handleBeforeUpload"
          :on-success="handleUploadSuccess"
          :on-exceeded-size="handleMaxSize"
          :on-format-error="handleFormatError"
          :on-error="handleUploadError"
          type="drag"
          style="display: inline-block"
          :style="{ width: `${uploadWindowWidth}px` }"
          :action="uploadUrl"
        >
          <div
            v-if="fileType != 2"
            style="
                            width: 58px;
                            height: 58px;
                            line-height: 58px;
                            border: 1px dashed #dcdee2;
                            border-radius: 6px;
                        "
          >
            <Icon :type="computeIcon" size="20" />
          </div>
        </Upload>
        <Poptip v-else v-model="showAudioModal">
          <Button @click="showRecorder = false">
            选择音频素材
          </Button>
          <template #content>
            <div>
              <div style="display: flex; padding: 10px 18px">
                <Upload
                  ref="uploadLogRef"
                  :headers="headers"
                  :multiple="multiple"
                  :show-upload-list="false"
                  :format="format"
                  :accept="accept"
                  :max-size="maxSize"
                  :data="data"
                  :before-upload="handleBeforeUpload"
                  :on-success="handleUploadSuccess"
                  :on-exceeded-size="handleMaxSize"
                  :on-format-error="handleFormatError"
                  :on-error="handleUploadError"
                  type="drag"
                  style="display: inline-block"
                  :action="uploadUrl"
                >
                  <Button>本地音频文件</Button>
                </Upload>
                <Button style="margin-left: 20px" @click="record">
                  录音
                </Button>
              </div>
              <Recorder
                v-show="showRecorder"
                ref="rec"
                style="float: right"
                @getRecordFile="getRecordFile"
              />
            </div>
          </template>
        </Poptip>
        <slot />
      </li>
    </ul>

    <Modal v-model="showVideoModal" width="963" title="视频播放">
      <div style="width: 750px; height: 500px; margin: auto">
        <video
          v-if="fileType === 3"
          ref="videoRef"
          autoplay
          style="width: 100%; height: 100%"
          :src="currentUrl"
          controls="controls"
        />
      </div>
    </Modal>
  </div>
</template>

<script>
import Viewer from 'viewerjs'
import 'viewerjs/dist/viewer.css'
import axios from 'axios'
import Recorder from '../../views/family-school/evaluation/component/recorder.vue'

export default {
  name: 'S3Upload',
  components: { Recorder },
  props: {
    defaultFileList: {
      default: () => {
        return []
      }
    },
    ifEdit: {
      default: true
    },
    maxLength: {
      default: 1
    },
    type: '',
    maxSize: {
      default: 5120,
      type: Number
    },
    multiple: {
      default: false
    },
    format: {
      default: () => {
        return ['jpg', 'jpeg', 'png', 'mp3', 'mp4', 'mav', 'mv']
      },
      type: Array
    },
    accept: {
      default: ''
    },
    fileType: {
      default: 1
    },
    showUploadList: {
      default: false
    },
    uploadWindowWidth: {
      default: 58
    },
    clearMargin: {
      default: false
    },
    successTrigger: {
      default: false
    },
    needRemove: {
      type: Boolean,
      default: true
    },
    isCut: {
      default: true,
      type: Boolean
    }
  },
  data () {
    return {
      showRecorder: false,
      uploadFile: [],
      uploadUrl: '',
      headers: {},
      data: {},
      imageUrl: new Map(),
      currentUrl: '',
      showAudioModal: false,
      showVideoModal: false,
      errorCode: 0,
      shouldRest: false
    }
  },
  computed: {
    computeIcon () {
      if (this.fileType === 1) { return 'ios-camera' } else if (this.fileType === 2) { return 'md-volume-up' } else { return 'ios-videocam' }
    }
  },
  watch: {
    /*            defaultList() {
                                if (this.defaultList) {
                                    this.init()
                                }
                            }, */
    defaultFileList () {
      if (this.defaultFileList) { this.init() }
    }
    /*            oneList() {
                                if (this.oneList) {
                                    this.init();
                                }
                            } */
  },
  mounted () {
    this.init()
  },
  methods: {
    handleTrackUpload (index, item) {
      const link = this.uploadFile[index]
      this.uploadFile.splice(index, 1)
      this.$refs.uploadLogRef.$el.children[0].click()
      this.uploadFile.push(link)
      this.shouldRest = true
    },
    getRecordFile (file) {
      const param = { type: this.type, contentType: file.type, fileName: file.name }
      this.sign(param)
        .then((res) => {
          this.imageUrl.set(file.name, res.url)
          this.fileKey = file.name
          delete res.url
          const formData = new FormData()
          for (const k in res) { formData.append(k, res[k]) }

          formData.append('file', file)
          axios
            .post(this.uploadUrl, formData, { headers: { 'Content-Type': 'multipart/form-data' } })
            .then((res) => {
              if (this.uploadFile.length < this.maxLength) { this.uploadFile.push({ type: this.fileType, url: this.imageUrl.get(file.name) }) }
            })
        })
        .catch((e) => {
          this.$Message.error({
            content: '文件获取签名失败，请联系管理人员',
            duration: 3
          })
          return false
        })
    },
    record () {
      this.showRecorder = true
      this.$refs.rec.init()
    },
    getFileList () {
      return this.uploadFile
    },
    init () {
      this.uploadFile = this.defaultFileList
    },
    clear () {
      this.uploadFile = []
    },
    handleView (item) {
      if (this.fileType === 3) {
        this.currentUrl = item.url
        this.showVideoModal = true
        this.$refs.videoRef.play()
      } else if (this.fileType === 2) {
        this.currentUrl = item.url
        this.showAudioModal = true
        this.$refs.audioRef.play()
      } else {
        const image = new Image()
        image.src = item.url
        const viewer = new Viewer(image, {
          zIndex: 99999999,
          hidden () {
            viewer.destroy()
          }
        })
        viewer.show()
      }
    },
    async handleUploadSuccess (res, file, fileList) {
      // 针对handleBeforeUpload 返回false时应走handleUploadError方法，实际走了handleUploadSuccess的特殊处理
      if (this.fileType === 2 && !this.imageUrl.get(file.name)) {
        this.errorCode = 1001
        this.handleUploadError('', file, fileList)
      } else {
        if (this.uploadFile.length < this.maxLength) { this.uploadFile.push({ type: this.fileType, url: this.imageUrl.get(file.name), name: file.name }) }

        if (this.shouldRest) {
          this.uploadFile = [{ type: this.fileType, url: this.imageUrl.get(file.name), name: file.name }]
          this.shouldRest = false
        }
      }
      if (this.successTrigger) { this.$emit('uploadSuccess', this.uploadFile) }
    },
    handleUploadError (error, file, fileList) {
      if (this.errorCode === 1001) {
        this.$Message.error({
          content: '音频不得超过10分钟，请重新上传',
          duration: 2
        })
      } else {
        this.$Message.error({
          content: `【${error}】，上传失败`,
          duration: 2
        })
      }
    },
    handleRemove (index, item) {
      this.uploadFile.splice(index, 1)
      this.$refs.uploadLogRef.clearFiles()
      this.$Message.success('移除成功')
    },
    handleMaxSize (file) {
      this.$Message.error({
        content: `【${file.name}】文件超过【${this.maxSize}KB】大小，上传失败`,
        duration: 3
      })
    },
    handleFormatError (file) {
      this.$Message.error({
        content: `【${file.name}】文件格式不支持，当前只支持【${this.format}】格式`,
        duration: 3
      })
    },
    async handleBeforeUpload (file) {
      const param = { type: this.type, contentType: file.type, fileName: file.name }
      let ret = true
      if (this.fileType === 2) {
        await this.getDuration(file).then((res) => {
          if (res > 600) {
            this.errorCode = 1001
            ret = false
          }
        })
        if (!ret) { return false }
      }
      await this.sign(param)
        .then((res) => {
          this.imageUrl.set(file.name, res.url)
          delete res.url
          this.data = res
        })
        .catch((e) => {
          this.$Message.error({
            content: '文件获取签名失败，请联系管理人员',
            duration: 3
          })
          return false
        })

      const curSize = this.defaultFileList.length + this.$refs.uploadLogRef.fileList.length
      if (curSize > this.maxLength) { return false }

      return this.uploadFile.length <= this.maxLength
    },
    async sign (param) {
      return new Promise((resolve, reject) => {
        this.$serverApi.getSign(param).then((res) => {
          if (res.success) { resolve(res.data) }

          reject()
        })
      })
    },
    async getDuration (file) {
      let audioDuration = 0
      const url = URL.createObjectURL(file)
      const audioElement = new Audio(url)
      return new Promise((resolve, reject) => {
        audioElement.onloadedmetadata = () => {
          audioDuration = Number.parseInt(audioElement.duration)
          resolve(audioDuration)
        }
      })
    }
  }
}
</script>

<style scoped lang="less">
.demo-upload-list {
    display: inline-block;
    width: 100px;
    height: 100px;
    text-align: center;
    /*line-height: 60px;*/
    border: 1px solid transparent;
    border-radius: 4px;
    overflow: hidden;
    background: #fff;
    position: relative;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
    /*margin-right: 10px;*/
    margin: 0 30px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.clear-margin {
    margin: 0;
}

.demo-upload-list img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.demo-upload-list-cover {
    display: none;
    position: absolute;
    width: 60px;
    height: 60px;
    top: 0px;
    bottom: 0;
    left: 0;
    right: 0;
    background: rgba(0, 0, 0, 0.6);
}

.demo-upload-list:hover .demo-upload-list-cover {
    display: block;
}

.demo-upload-list-cover i {
    color: #fff;
    font-size: 20px;
    cursor: pointer;
    margin: 0 2px;
}

ul {
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;

    width: 100%;
    height: 100%;
}

li {
    list-style: none;
    text-align: center;
    border-radius: 5px;
    height: 40%;
    /*margin-right: 10%;*/
    /*margin-bottom: 5%;*/
}

/*li:nth-of-type(3n) {*/
/*    margin-right: 0;*/
/*}*/

/*li:nth-of-type(n+7) {*/
/*    margin-bottom: 0;*/
/*}*/

/deep/ .ivu-upload-drag {
    border: 0px;
}

.file-list {
    display: flex;
    flex-direction: row;
    align-items: center;
}

.file-list_upload {
    display: flex;
    align-items: center;
    justify-content: center;
}

.cat_div {
    display: flex;
    justify-content: center;
    align-items: center;
    margin-top: 4px;
    margin-left: auto;
    margin-right: auto;
}
.cat_img {
    object-fit: cover;
}
</style>
